#include <iostream>
#include <string>
#include <vector>
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <wait.h>
using namespace std;
#include "Task.hpp"

const int num = 5;

static int cnt = 1;
// 需要对信道进行先描述，在组织
class channel
{
public:
    channel(int r, pid_t id)
        : readfd(r), workrid(id)
    {
        name = "channel_" + to_string(cnt);
        cnt++;
    }

public:
    int readfd;
    pid_t workrid;
    string name;
};

void Work()
{
    while (true)
    {
        int code = 0;
        int n = read(0, &code, sizeof(code));
        if (n == 4)
        {
            init.RunTask(code);
        }
        else if (n == 0)
        {

            break;
        }
    }
}

void CreateChannel(vector<channel> *channels)
{
    for (int i = 0; i < num; i++)
    {
        int pipefd[2] = {0};
        int n = pipe(pipefd);
        assert(n == 0); // 这里认为管道pipe一定执行成功
        (void)n;

        // 父写，子读
        pid_t id = fork();
        if (id < 0)
        {
            perror("fork");
        }
        else if (id == 0)
        {
            // chile
            close(pipefd[1]);
            dup2(pipefd[0], 0); // 重定向更加方便操作
            Work();
            exit(0);
        }

        // father
        close(pipefd[0]);
        // 创建信道的时候就进行管理
        channels->push_back(channel(pipefd[1], id));
    }
}

void SendCommand(vector<channel> &channels, int n = -1)
{
    int count = 0;
    int i = 0;
    while (true)
    {

        int code = init.RandomSending();
        write(channels[i].readfd, &code, sizeof(code));
        i %= channels.size();
        cout << "选择信道 :"
             << "[" << i + 1 << "]"
             << " name : " << channels[i].name << " 执行 :" << init.HashName(code) << endl;
        count++;
        i++;
        if (n != -1 && count >= n)
        {
            break;
        }
        sleep(1);
    }
    cout << " 指定任务: " << n << "条发放成功" << endl;
}

void ReleaseChannels(vector<channel> &channels)
{
    // 关闭写端

    // // 回收子进程
    // f1
    for (int i = channels.size() - 1; i >= 0; i--)
    {
        close(channels[i].readfd);
        int rid = waitpid(channels[i].workrid, nullptr, 0);
        if (rid == channels[i].workrid)
        {
            cout << "wait child : " << rid << " success !" << endl;
        }
    }

    // f2 (errror)    // 子进程中也有很多文件描述符指向写端 (所以正常顺序不能关闭)
    //  for (auto ch : channels)
    //  {
    //      close(ch.readfd);
    //      int rid = waitpid(ch.workrid, nullptr, 0);
    //  }

    // f3
    // for (auto ch : channels)
    // {
    //     close(ch.readfd);
    // }

    // for (auto ch : channels)
    // {
    //     int rid = waitpid(ch.workrid, nullptr, 0);
    //     if (rid == ch.workrid)
    //     {
    //         cout << "wait child : " << rid << " success !" << endl;
    //     }
    // }
    cout << "wait cuccess ! ! !" << endl;
}

int main()
{
    vector<channel> channels;
    //  第一步创建子进程,创建信道
    CreateChannel(&channels);
    // 开始发送任务
    SendCommand(channels);
    // 回收资源
    ReleaseChannels(channels);
    return 0;
}